#include "Geom/Vector.h"

namespace geom
{

    //-------------------------------------------------------------------------------------------------------------------
    inline Point::Point() : m_point(0, 0, 0, 1)
    //-------------------------------------------------------------------------------------------------------------------
    {
    }

    //-------------------------------------------------------------------------------------------------------------------
    inline Point::Point(double p_x, double p_y, double p_z) : m_point(p_x, p_y, p_z, 1)
    //-------------------------------------------------------------------------------------------------------------------
    {
    }

    //-------------------------------------------------------------------------------------------------------------------
    inline Point::Point(const Point& p_point) : m_point(p_point.m_point)
    //-------------------------------------------------------------------------------------------------------------------
    {
    }

    //-------------------------------------------------------------------------------------------------------------------
    inline void Point::set(double p_x, double p_y, double p_z)
    //-------------------------------------------------------------------------------------------------------------------
    {
        m_point.set(p_x, p_y, p_z, 1);
    }

    //-------------------------------------------------------------------------------------------------------------------
    inline Point Point::add(double dx, double dy, double dz) const
    //-------------------------------------------------------------------------------------------------------------------
    {
        return Point(x() + dx, y() + dy, z() + dz);
    }

    //-------------------------------------------------------------------------------------------------------------------
    inline Point Point::mul(double mx, double my, double mz) const
    //-------------------------------------------------------------------------------------------------------------------
    {
        return Point(x() * mx, y() * my, z() * mz);
    }

    //-------------------------------------------------------------------------------------------------------------------
    inline void Point::x(double p_x)
    //-------------------------------------------------------------------------------------------------------------------
    {
        m_point.at(0) = p_x;
    }

    //-------------------------------------------------------------------------------------------------------------------
    inline void Point::y(double p_y)
    //-------------------------------------------------------------------------------------------------------------------
    {
        m_point.at(1) = p_y;
    }

    //-------------------------------------------------------------------------------------------------------------------
    inline void Point::z(double p_z)
    //-------------------------------------------------------------------------------------------------------------------
    {
        m_point.at(2) = p_z;
    }


    //ACCESSORS

    //-------------------------------------------------------------------------------------------------------------------
    inline double Point::x() const
    //-------------------------------------------------------------------------------------------------------------------
    {
        return m_point.at(0);
    }

    //-------------------------------------------------------------------------------------------------------------------
    inline double Point::y() const
    //-------------------------------------------------------------------------------------------------------------------
    {
        return m_point.at(1);
    }

    //-------------------------------------------------------------------------------------------------------------------
    inline double Point::z() const
    //-------------------------------------------------------------------------------------------------------------------
    {
        return m_point.at(2);
    }

    //-------------------------------------------------------------------------------------------------------------------
    inline double Point::distance(const Point& other) const
    //-------------------------------------------------------------------------------------------------------------------
    {
        return sqrt(squaredDistance(other));
    }

    //-------------------------------------------------------------------------------------------------------------------
    inline double Point::squaredDistance(const Point& other) const
    //-------------------------------------------------------------------------------------------------------------------
    {
        const double xDist = x() - other.x();
        const double yDist = y() - other.y();
        const double zDist = z() - other.z();

        return xDist*xDist + yDist*yDist + zDist*zDist;
    }

    // OPERATORS

    //-----------------------------------------------------------------------------------
    inline bool Point::operator==(const Point& p_other) const
    //-----------------------------------------------------------------------------------
    {
        return m_point == p_other.m_point;
    }

    //-----------------------------------------------------------------------------------
    inline bool Point::operator!=(const Point& p_other) const
    //-----------------------------------------------------------------------------------
    {
        return m_point != p_other.m_point;
    }

    //-----------------------------------------------------------------------------------
    inline Point& Point::operator=(const Point& p_other)
    //-----------------------------------------------------------------------------------
    {
        m_point = p_other.m_point;
        return (*this);
    }

    //-----------------------------------------------------------------------------------
    inline Point Point::operator+(const Vector& p_vec) const
    //-----------------------------------------------------------------------------------
    {
        return Point(x() + p_vec.x(), y() + p_vec.y(), z() + p_vec.z());
    }

    //-----------------------------------------------------------------------------------
    inline Point& Point::operator+=(const Vector& p_vec)
    //-----------------------------------------------------------------------------------
    {
        m_point += p_vec.m_vec;
        return (*this);
    }

    //-----------------------------------------------------------------------------------
    inline Vector Point::operator-(const Point& p_other) const
    //-----------------------------------------------------------------------------------
    {
        Vector v;
        v.m_vec = m_point - p_other.m_point;
        return v;
    }
}
